<?php

class mod_authz_svn {
	
	private $htpasswd;
	

	private $defaultAccessContent = "";
	private $modifiedAccessContent = "";
	
	private $aliases = array();
	private $groups = array();
	private $users = array();
	private $repositories = array();
	private $accessToListRepos = array();
	
	
    public function __construct($access) {
    	
		$this->accessFile = $access;
		
		$this->defaultAccessContent = file_get_contents($this->accessFile);
		$this->parseAuthFile();
    }
    
    private function parseAuthFile() {
    	$lines = explode("\n", $this->defaultAccessContent);
    	
    	$mode = "begin";
    	$repoName = '';
    	
    	$pattern = '/\[(.*?)\]/';
    	foreach($lines as $line) {
    		$line = trim($line);
    		if($line != '' && $line{0} != '#') {
    		
	        	preg_match($pattern, $line, $matches);
	    		if(isset($matches[1])) {
		    		if($matches[1] == 'aliases') {
	    				//finding aliases
	    				$mode = "aliases";
	    			}
	    			else if($matches[1] == 'groups') {
	    				//finding groups
	    				$mode = "groups";
	    			}
	    			else if($matches[1] == '/') {
	    				//finding groups
	    				$mode = "list";
	    			}
	    			else {
	    				//finding repos
	    				$mode = "repos";
	    				$repoParts = explode(':', trim($matches[1]));
	    				$repoName = trim($repoParts[0]);
	    				$location = trim($repoParts[1]);
	    				$this->repositories[] = new repo($repoName, $location);
	    			}
	    		}
	    		else if($mode == 'aliases') {
	    			
					$parts = explode('=', $line, 2);
					$name = trim($parts[0]);
					$alias = trim($parts[1]);

					$this->aliases[] = new alias($name, $alias);
				
	    		}
	    		else if($mode == 'groups') {
	    			
					$parts = explode('=', $line);
					$userParts = explode(',', trim($parts[1]));
		
					$users = array();
					foreach($userParts as $username) {
						$username = trim($username);
						if($username != '') {
							$users[] = new user($username);
						}
					}
					$this->groups[] = new group(trim($parts[0]), $users);
	    		}
	    		else if($mode == 'list') {
	    			
					$parts = explode('=', $line);
					$username = trim($parts[0]);
					$permissions = trim($parts[1]);
					
					if($permissions = 'r' || $permissions = 'rw') {
						$this->accessToListRepos[] = $username;
					}
	    		}
	    		else if($mode == 'repos') {
	    			$last = count($this->repositories)-1;
					
	    			$parts = explode('=', $line);
					$username = trim($parts[0]);
					$permissions = trim($parts[1]);
					
					$read = false;
					$write = false;
					
		    		if($permissions == 'rw') {
						$read = true;
						$write = true;
					}
					else if($permissions == 'r') {
						$read = true;
						$write = false;
					}
					else if($permissions == 'w') {
						$read = false;
						$write = true;
					}
	    			$this->repositories[$last]->addUser(new user($username, $read, $write));
	    		}
    		}
    	}
    	
    }
    private function generateContent($generateHelpContent = false) {
    	$this->modifiedAccessContent = '';
    	if($generateHelpContent) {
    	$this->modifiedAccessContent = 	'### This file is an autogenerated authorization file for svnserve.' . "\n" .
					'### Its format is identical to that of mod_authz_svn authorization' . "\n" .
					'### files.' . "\n" .
					'### As shown below each section defines authorizations for the path and' . "\n" .
					'### (optional) repository specified by the section name.' . "\n" .
					'### The authorizations follow. An authorization line can refer to:' . "\n" .
					'###  - a single user,' . "\n" .
					'###  - a group of users defined in a special [groups] section,' . "\n" .
					'###  - an alias defined in a special [aliases] section,' . "\n" .
					'###  - all authenticated users, using the \'\' token,' . "\n" .
					'###  - only anonymous users, using the \'\' token,' . "\n" .
					'###  - anyone, using the \'*\' wildcard.' . "\n" .
					'###' . "\n" .
					'### A match can be inverted by prefixing the rule with \'~\'. Rules can' . "\n" .
					'### grant read (\'r\') access, read-write (\'rw\') access, or no access' . "\n" .
					'### (\'\').' . "\n\n\n";
    	}
    	
    	
        $this->modifiedAccessContent .= "[aliases]\n";
        if($generateHelpContent) {
        	$this->modifiedAccessContent .= "# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average\n"; //SAMPLE
        }
    	foreach($this->aliases as $alias) {
			$this->modifiedAccessContent .= $alias->getName() . ' = ' . $alias->getAlias() . "\n";
    	}
    	
        $this->modifiedAccessContent .= "\n\n[groups]\n";
        if($generateHelpContent) {
			$this->modifiedAccessContent .= "# harry_and_sally = harry,sally\n";
			$this->modifiedAccessContent .= "# harry_sally_and_joe = harry,sally,&joe\n";
        }
        
    	foreach($this->groups as $group) {
    		$users = array();
    		foreach($group->getUsers() as $user) {
    			$users[] = $user->getUsername();
    		}
			$this->modifiedAccessContent .= $group->getName(). ' = ' . implode(',', $users) . "\n";
    	}
    	if($generateHelpContent) {
	    	$this->modifiedAccessContent .= "\n";
	    	$this->modifiedAccessContent .= "\n";
			$this->modifiedAccessContent .= "# [/foo/bar]" . "\n";
			$this->modifiedAccessContent .= "# harry = rw" . "\n";
			$this->modifiedAccessContent .= "# &joe = r" . "\n";
			$this->modifiedAccessContent .= "# * =" . "\n";
			$this->modifiedAccessContent .= "\n";
			$this->modifiedAccessContent .= "# [repository:/baz/fuz]" . "\n";
			$this->modifiedAccessContent .= "# @harry_and_sally = rw" . "\n";
			$this->modifiedAccessContent .= "# * = r" . "\n";
    	}
    	
        $this->modifiedAccessContent .= "\n\n[/]\n";
    	foreach($this->accessToListRepos as $user) {
        	$this->modifiedAccessContent .= $user. ' = r' . "\n";
    	}
		
    	foreach($this->repositories as $repo) {
        	$this->modifiedAccessContent .= "\n\n[".$repo->getName().":" . $repo->getLocation() . "]\n";
    		
    		$users = array();
    		foreach($repo->getUsers() as $user) {
    			
    			$this->modifiedAccessContent .= $user->getUsername(). ' = ' . $user->getPermissions() . "\n";
    		}
    	}
   		
    }
    
    public function removeUser($username) {

    	foreach($this->repositories as $repo) {
    		$repo->deleteUser($username);
    	}
    	
    	//removes a value from an array if exists
    	array_splice($this->accessToListRepos, array_search($username, $this->accessToListRepos), in_array($username, $this->accessToListRepos));
    	$this->saveModifiedContent();
    }
    
    public function deleteRepo($reposotory) {
        $repos = array();
        $result = false;
        foreach($this->repositories as $repo) {
            if($repo->getName() != $reposotory) {
                $repos[] = $repo;
            } else {
                $result = true;
            }
        }
        $this->repositories = $repos;
        $this->saveModifiedContent();
        return $result;
    }
    public function checkRepo($repoName) {
        $repos = $this->getRepos();
        foreach($repos as $repo) {
            if($repo->getName() == $repoName) {
                return true;
            }
        }
        return false;
    }
    public function addRepo($repoName, $users) {
    	if($this->checkRepo($repoName) == true) return false;
    	
    	$this->repositories[] = new repo($repoName, '/');

	    $last = count($this->repositories)-1;
	    foreach($users as $user) {
	    	$this->repositories[$last]->addUser($user);
	    }
	    $this->saveModifiedContent();
    }
    
    public function getGroups() {
    	return $this->groups;
    }
    public function getAliases() {
    	return $this->aliases;
    }
    public function getRepos() {
    	return $this->repositories;
    }
    public function getRepo($repository) {
        $repos = $this->getRepos();
        foreach($repos as $repo) {
            if($repo->getName() == $repository) {
                return $repo;
            }
        }
        return false;
    }
	public function getListAccess() {
    	return $this->accessToListRepos;
    }
	public function setListAccess($usernames) {
    	$this->accessToListRepos = $usernames;
    	$this->saveModifiedContent();
    }
    public function changeRepo($repository, $users) {
        $repos = $this->getRepos();
        $newRepos = array();
        foreach($repos as $repo) {
            if($repo->getName() == $repository->getName()) {
		    	
		    	$newRepos[] = new repo($repository->getName(), $repository->getLocation());
		
			    $last = count($newRepos)-1;
			    foreach($users as $user) {
			    	$newRepos[$last]->addUser($user);
			    }
            }
            else {
            	$newRepos[] = $repo;
            }
        }
        $this->repositories = $newRepos;
        $this->saveModifiedContent();
    }

    public function getDefaultContent() {
    	return $this->defaultAccessContent; 
    }
    public function getModifiedContent() {
    	$this->generateContent();
    	return $this->modifiedAccessContent; 
    }
    public function saveModifiedContent() {
    	file_put_contents($this->accessFile, $this->getModifiedContent());
    }
    
}


?>